﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LGPeWJNM.BaseClasses;

namespace LGPeWJNM.TeitzComGillet
{
    /// <summary>
    /// Implementação de uma solução inicial com Monte Carlo e Gillet Johnson
    /// </summary>
    public class McG : ISolucaoInicial
    {
        private Random Rnd { get; set; }

        /// <summary>
        /// Construtor padrão
        /// </summary>
        public McG()
        {
            Rnd = new Random();
        }
        /// <summary>
        /// Método de designação por Gillet Johnson a partir de medianas geradas por Monte Carlo
        /// </summary>
        /// <param name="destinos">Conjuntos desordenado de coordenadas de destinos</param>
        /// <param name="deposito">Coordenadas do depósito</param>
        /// <param name="quantidadeVeiculos">Número de veículos disponíveis para a roteirização</param>
        /// <param name="capacidadeVeiculo">Capacidade de carga de cada veículo</param>
        /// <returns>Conjunto de grupos de clientes</returns>
        public IEnumerable<IEnumerable<ICliente>> Processar(IEnumerable<ICliente> destinos, Point deposito, int quantidadeVeiculos, float capacidadeVeiculo)
        {
            var meds = MonteCarlo(destinos, quantidadeVeiculos, capacidadeVeiculo);
            var retorno = GilletJohnson.Clusterizacao(meds, destinos, deposito, capacidadeVeiculo);
            return retorno;
        }

        private IEnumerable<mMediana> MonteCarlo(IEnumerable<ICliente> destinos, int quantidadeVeiculos, float capacidadeVeiculo)
        {
            double xMin = destinos.Select(s => s.Coordenada.X).Min();
            double xMax = destinos.Select(s => s.Coordenada.X).Max();
            double yMin = destinos.Select(s => s.Coordenada.Y).Min();
            double yMax = destinos.Select(s => s.Coordenada.Y).Max();

            for (int i = 0; i < quantidadeVeiculos; i++)
            {
                yield return new mMediana(new Point()
                {
                    X = Rnd.NextDouble() * (xMax - xMin) + xMin,
                    Y = Rnd.NextDouble() * (yMax - yMin) + yMin,
                }, capacidadeVeiculo);
            }
        }
    }
}
